package com.msteam.tools.code.generator;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import javax.sql.DataSource;

import org.apache.commons.io.FileUtils;

import com.alibaba.fastjson.JSON;

import com.google.gson.Gson;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.DbKit;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.generator.ColumnMeta;
import com.jfinal.plugin.activerecord.generator.TableMeta;
import com.jfinal.plugin.druid.DruidPlugin;
import com.msteam.kernel.util.ClassUtils;
import com.msteam.tools.code.generator.Property.ColumnStruct;
import com.msteam.tools.code.generator.Property.EntityVariable;
import com.msteam.tools.code.generator.Property.FieldVariable;
import com.msteam.tools.code.generator.Property.GenerateVariable;
import com.msteam.tools.code.generator.Property.TableStruct;
import com.msteam.tools.code.generator.template.FileMeta;
import com.msteam.tools.code.generator.template.GenType;
import com.msteam.tools.code.model.CbhColumn;
import com.msteam.tools.code.model.CbhProject;
import com.msteam.tools.code.model.CbhTable;
import com.msteam.tools.code.model.CbhTemplate;
import com.msteam.tools.code.model.CbhTemplateFile;
import com.msteam.tools.code.model.json.CbhProjectJson;
import com.msteam.tools.code.model.json.CbhTableJson;

public class CubeHandGenerator {
	
	//private String _packageName;
	//private String _templateName;
	//private String _outputDir;
	//private String _filenameTemplate;
	//private NamingMode _namingMode;
	
	
	private List<TableMeta> _metas = null;
	private CubeHandMetaBuilder _mmbuilder;
	private CbhProject _project = null;
	private CbhProjectJson _projectJson = null;
	private List<EntityVariable> _tables = null;
	
	private DruidPlugin _dp =null;
	
	private ActiveRecordPlugin _arp = null;
	
	private String TEMPLATE_DISK="G:";
	/**
	 * 构造生成器
	 * @param project
	 */
	public CubeHandGenerator(CbhProject project){
		_project = project;
		_projectJson = _wrapCbhProjectJsonItem(_project);
		_mmbuilder = new CubeHandMetaBuilder(getDataSource(project));
	}
	
	/**
	 * 生成数据模型
	 * @return
	 */
	public List<TableMeta> buildMetas(){
		_metas = _mmbuilder.build();
		return _metas;
	}
	
	/**
	 * 刷新项目的表和列定义
	 */
	public void refreshProjectTableColumns(){
		if(_metas==null){
			this.buildMetas();
		}
		// 初始化数据源插件
		this.loadArp();
		
		DbPro dbPro = Db.use("ds_"+_project.getID());
		for(TableMeta tm:_metas){
			// 表名注释
            String tableNameComment = dbPro.findFirst("select table_comment from information_schema.tables where table_schema=? and table_name = ?", _project.getDbName(), tm.name).getStr("table_comment");
            // 表所有字段集合
            List<Record> columnComments = dbPro.find("select column_name, column_comment,DATA_TYPE,COLUMN_TYPE from information_schema.columns where table_schema=? and table_name = ?", _project.getDbName(), tm.name);
            
			CbhTable gt = CbhTable.dao.findFirst("select * from cbh_table where PROJECT_ID=? and TABLE_NAME=?", _project.getID(), tm.name);
			if(gt == null){
				gt = new CbhTable();
				gt.setProjectId(_project.getID());
				
				gt.setModelName(tm.modelName);
				//String prefix = tm.name.substring(tm.name.indexOf("_")+1).toLowerCase();
				String prefix = tm.name.split("_")[0];
				gt.setPREFIX(prefix);
				gt.setPrimaryKey(tm.primaryKey);
				if(StrKit.isBlank(tm.remarks)){
					gt.setREMARKS(tableNameComment);
					gt.setDisplayName(tableNameComment);
				}else{
					gt.setREMARKS(tm.remarks);	
					gt.setDisplayName(tm.remarks);
				}
				
				gt.setTableName(tm.name);
				gt.setIsProcess(true);
				
				gt.save();
			}
			Integer tableId = gt.get("ID");
			for(ColumnMeta cm : tm.columnMetas){
				CbhColumn gc = CbhColumn.dao.findFirst("select * from cbh_column where TABLE_ID=? and NAME=?", tableId, cm.name);
				if(gc == null){
					gc = new CbhColumn();
					gc.setTableId(tableId);
					gc.setAttrName(cm.attrName);
					gc.setDefaultValue(cm.defaultValue);
					
					gc.setInEdit(true);
					gc.setInList(true);
					gc.setInView(true);
					gc.setFrontInEdit(false);
					gc.setFrontInList(false);
					gc.setFrontInView(false);			
					
					gc.setIsApply(false);
					gc.setIsNullAble("YES".equalsIgnoreCase(cm.isNullable));
					gc.setIsPrimaryKey(cm.name.equalsIgnoreCase(tm.primaryKey));
					if(gc.getIsPrimaryKey()){
						gc.setInputType("HIDDEN");
					}else{
						gc.setInputType("INPUT");
					}
					gc.setJavaType(cm.javaType);

					gc.setNAME(cm.name);
					//gc.setQueryBy(false);
					gc.setQueryBy(true);
					gc.setOrderBy(true);
					
					if(StrKit.isBlank(tm.remarks)){
						String remarks = "";
						for (Record comment : columnComments) {
			                // 表字段列名
			                String columnName = comment.getStr("column_name");
			                if(cm.name.equalsIgnoreCase(columnName)){
				                // 字段注释
				                remarks = comment.getStr("column_comment");
			                }
			            }
						gc.setREMARKS(remarks);
						gc.setDisplayName(remarks);
					}else{
						gc.setREMARKS(cm.remarks);
						gc.setDisplayName(cm.remarks);
					}
					gc.setTYPE(cm.type);
					for (Record comment : columnComments) {
		                // 表字段列名
		                String columnName = comment.getStr("column_name");
		                if(cm.name.equalsIgnoreCase(columnName)){
			                // 字段注释
			                gc.setTYPE(comment.getStr("DATA_TYPE"));
			                String columnType = comment.getStr("COLUMN_TYPE");
			                if(columnType.indexOf("(")>-1){
			                	String ctls = columnType.split("\\(")[1];
			                	gc.setSize(ctls.replace(")", ""));
			                }else{
			                	gc.setSize("0");
			                }
		                }
		            }
					
					gc.save();
				}else{
					for (Record comment : columnComments) {
		                // 表字段列名
		                String columnName = comment.getStr("column_name");
		                if(cm.name.equalsIgnoreCase(columnName)){
			                // 字段注释
			                gc.setTYPE(comment.getStr("DATA_TYPE"));
			                String columnType = comment.getStr("COLUMN_TYPE");
			                if(columnType.indexOf("(")>-1){
			                	String ctls = columnType.split("\\(")[1];
			                	gc.setSize(ctls.replace(")", ""));
			                }else{
			                	gc.setSize("0");
			                }
		                }
		            }
					
					gc.update();
				}
			}
		}
	}
	/**
	 * 获取
	 * @param project
	 * @return
	 */
	public void loadArp() {
		if(_dp!=null){
			_dp.stop();
		}
		if(_arp!=null){
			_arp.stop();
		}
		String dbHost = _project.getDbHost();
		String dbName = _project.getDbName();
		String dbUser = _project.getDbUser();
		String dbPassword = _project.getDbPassword();
		
		String jdbc_url = "jdbc:mysql://" + dbHost + "/" + dbName;
		if(DbKit.getConfig("ds_"+_project.getID())==null){
			_dp = new DruidPlugin(jdbc_url, dbUser,dbPassword);
			
			_arp = new ActiveRecordPlugin("ds_"+_project.getID(), _dp);
			_dp.start();
			_arp.start();
		}
		
	}
	/**
	 * 获取数据源
	 * @param project
	 * @return
	 */
	public DataSource getDataSource(CbhProject project) {

		String dbHost = project.getDbHost();
		String dbName = project.getDbName();
		String dbUser = project.getDbUser();
		String dbPassword = project.getDbPassword();
		
		String jdbc_url = "jdbc:mysql://" + dbHost + "/" + dbName;
		
		DruidPlugin druidPlugin = new DruidPlugin(jdbc_url, dbUser,dbPassword);
		druidPlugin.start();
		return druidPlugin.getDataSource();
	}
	public void refreshTemplate() {
		List<CbhTemplate> ts = new CbhTemplate().find("select * from cbh_template where ID=?", _projectJson.getTEMPLATE_ID());
		for(CbhTemplate t : ts){
			//String tRoot = PathKit.getWebRootPath() +File.separatorChar+"WEB-INF"+File.separatorChar+"templates"+File.separatorChar+t.getCODE()+File.separatorChar;
			String tRoot = TEMPLATE_DISK+File.separatorChar+"CubeHandTemplates"+File.separatorChar+t.getCODE()+File.separatorChar;
			
			File rootDir = new File(tRoot);
			System.out.println("ROOT:"+rootDir.getAbsolutePath()+"-"+rootDir.getName()+"-"+rootDir.getPath()+":"+rootDir.getParent());
			try {
				List<File> templateFiles = listFiles(rootDir, true);
				for(File f:templateFiles){
					System.out.println(f.getPath());
				}
				for(File f:templateFiles){
					String fileName = f.getName();
					String fileAbsPath = f.getPath().replace(tRoot, "");
					String parentPath = f.getParentFile().getPath();
					
					Integer fileParentId = null;
					if(parentPath.length()>tRoot.length()){
						String parentAbsPath = parentPath.replace(tRoot, "");
						//System.out.println(f.getAbsolutePath()+"-"+f.getName()+"-"+f.getPath()+":"+f.getParentFile().getPath());
						System.out.println(fileName+"\t"+fileAbsPath+"\t"+parentAbsPath);
						System.out.println(_projectJson.getTEMPLATE_ID()+"  "+parentAbsPath);
						CbhTemplateFile tfParent = getDbTemplateFileDefine(_projectJson.getTEMPLATE_ID(), parentAbsPath);
						if(tfParent==null){
							System.out.println("NOT FOUND");
							Integer pparentId = null;
							String ppAbsPath = f.getParentFile().getParentFile().getPath().replace(tRoot, "");
							if(!StrKit.isBlank(ppAbsPath)){
								CbhTemplateFile ppf = getDbTemplateFileDefine(_projectJson.getTEMPLATE_ID(), ppAbsPath);
								if(ppf!=null){
									pparentId = ppf.getID();
								}
							}
							tfParent = new CbhTemplateFile();
							tfParent.setFileType("DIR");
							tfParent.setNAME(f.getParentFile().getName());
							tfParent.setParentId(pparentId);
							tfParent.setPATH(parentAbsPath);
							tfParent.setTemplateId(_projectJson.getTEMPLATE_ID());
							tfParent.save();
						}
						fileParentId = tfParent.getID();
					}
					CbhTemplateFile tf = getDbTemplateFileDefine(_projectJson.getTEMPLATE_ID(), fileAbsPath);
					if(tf==null){
						tf = new CbhTemplateFile();
						if(f.isDirectory()){
							tf.setFileType("DIR");
						}else{
							tf.setFileType("FILE");
						}
						tf.setNAME(fileName);
						tf.setParentId(fileParentId);
						tf.setPATH(fileAbsPath);
						tf.setProcessType("static");
						tf.setOutputPath(fileAbsPath);
						tf.setTemplateId(_projectJson.getTEMPLATE_ID());
						tf.save();
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			List<CbhTemplateFile> tfs = new CbhTemplateFile().find("select * from cbh_template_file where TEMPLATE_ID=? order by PARENT_ID desc, ID desc", _projectJson.getTEMPLATE_ID());
			for(CbhTemplateFile tf:tfs){
				File ttf = new File(tRoot + tf.getPATH());
				if(!ttf.exists()){
					tf.delete();
				}
			}
		}
	}
	private CbhTemplateFile getDbTemplateFileDefine(Integer templateId, String templateFilePath){
		CbhTemplateFile tf = new CbhTemplateFile().findFirst("select * from cbh_template_file where TEMPLATE_ID=? and PATH=?", templateId, templateFilePath);
		return tf;
	}
	/**
     * <pre>
     * 递归的列出文件
     * 
     * fileFilter ex.
     * fileFilter = new FileFilter() {
     *       public boolean accept(File pathname) {
     *           return !".svn".equals(pathname.getAbsolutePath());
     *       }
     *  };
     * </pre>
     * 
     * @param file
     * @param recusive
     * @param filter
     * @return
     * @throws java.io.IOException
     */
    public static List<File> listFiles(File file, boolean recusive) //
            throws IOException {
        List<File> fileList = new ArrayList<File>();
        if (file.isDirectory()) {
            Stack<File> stack = new Stack<File>();
            stack.push(file);
            File[] files;
            while (!stack.isEmpty()) {
                files = stack.pop().listFiles();
                for (File _file : files) {
                    if (_file.isDirectory() && recusive) {
                    	fileList.add(_file);
                        stack.push(_file);
                    } else if (_file.isFile()) {
                        fileList.add(_file);
                    }
                }
            }
        } else {
            if (file.exists()) {
                fileList.add(file);
            }
        }
        return fileList;
    }
	/**
	 * 加载生成的表设置
	 */
	private void loadTableSettings(){
		//Gson gson = new Gson();
		List<CbhTable> tables = new CbhTable().find("select * from cbh_table where PROJECT_ID=?", _project.getID());
		_tables = new ArrayList<EntityVariable>();
		for(CbhTable gt:tables){
			EntityVariable tj = new EntityVariable();

			tj.setDISPLAY_NAME(gt.getDisplayName());
			tj.setID(gt.getID());
			String tableName = gt.getTableName();
			
			String noprefixTablename = tableName.substring(tableName.indexOf("_")+1);
			String prefix = tableName.split("_")[0];
			String subTableName = tableName.replaceFirst(prefix+"_", "");
			String subModelName = StrKit.firstCharToUpperCase(StrKit.toCamelCase(subTableName));
			
			//tj.setSUB_MODEL_NAME(subModelName);
			//tj.setMODEL_NAME(StrKit.firstCharToUpperCase(prefix)+gt.getModelName());
			
			tj.setSUB_MODEL_NAME(gt.getModelName());
			tj.setMODEL_NAME(gt.getModelName());
			
			
			tj.setPACKAGE_NAME(gt.getPackageName());
			tj.setPRIMARY_KEY(gt.getPrimaryKey());
			tj.setREMARKS(gt.getREMARKS());
			tj.setTABLE_NAME(gt.getTableName());
			tj.setPREFIX(prefix);
			tj.setSUB_TABLE_NAME(subTableName);
			tj.setIS_PROCESS(gt.getIsProcess());
			tj.setEXTRA_INFO(gt.getExtraInfo());
			if(StrKit.isBlank(tj.getEXTRA_INFO())){
				tj.setExtra(new TableStruct(tj));
			}else{
				tj.setExtra(JSON.parseObject(tj.getEXTRA_INFO(), TableStruct.class));
			}
			if(tj.getTABLE_NAME().equalsIgnoreCase("ICT_DEMO")){
				System.out.println("");
			}
			List<FieldVariable> fields = new ArrayList<FieldVariable>();
			
			List<CbhColumn> gcs = new CbhColumn().find("select * from cbh_column where TABLE_ID=?", gt.getID());
			for(CbhColumn gc:gcs){
				FieldVariable cj = new FieldVariable();	
				cj.setATTR_NAME(gc.getAttrName());
				cj.setDEFAULT_VALUE(gc.getDefaultValue());
				cj.setDISPLAY_NAME(gc.getDisplayName());
				cj.setID(gc.getID());
				
				cj.setINPUT_TYPE(gc.getInputType());
				cj.setIN_EDIT(gc.getInEdit());
				cj.setIN_LIST(gc.getInList());
				cj.setIN_VIEW(gc.getInView());
				
				cj.setFRONT_IN_EDIT(gc.getFrontInEdit());
				cj.setFRONT_IN_LIST(gc.getFrontInList());
				cj.setFRONT_IN_VIEW(gc.getFrontInView());
				
				
				cj.setIS_APPLY(gc.getIsApply());
				cj.setIS_NULL_ABLE(gc.getIsNullAble());
				cj.setIS_PRIMARY_KEY(gc.getIsPrimaryKey());
				cj.setJAVA_TYPE(gc.getJavaType().replace("java.lang.", ""));
				cj.setNAME(gc.getNAME());
				cj.setQUERY_BY(gc.getQueryBy());
				cj.setORDER_BY(gc.getOrderBy());
				cj.setREMARKS(gc.getREMARKS());
				cj.setTABLE_ID(gc.getTableId());
				cj.setTYPE(gc.getTYPE());
				cj.setEXTRA_INFO(gc.getExtraInfo());
				if(StrKit.isBlank(cj.getEXTRA_INFO())){
					cj.setExtra(new ColumnStruct(cj));
				}else{
					cj.setExtra(JSON.parseObject(cj.getEXTRA_INFO(), ColumnStruct.class));
				}
				
				fields.add(cj);
			}
			tj.setFields(fields);
			
			_tables.add(tj);
		}
	}
	private String inputStreamToString(InputStream in){
		byte[] buffer = new byte[2048];
        int readBytes = 0;
        StringBuilder stringBuilder = new StringBuilder();
        
        try {
			while((readBytes = in.read(buffer)) > 0){
			    stringBuilder.append(new String(buffer, 0, readBytes));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
        return stringBuilder.toString();
	}

	/**
	 * 获取模版
	 * @return
	 */
	private List<FileMeta> getTemplates(){
		List<FileMeta> fms = new ArrayList<FileMeta>();
		
		List<Class<FileMeta>> controllerClassList = ClassUtils.scanSubClass(FileMeta.class, true);
		//System.out.println("classList Size:"+controllerClassList.size());
		if (controllerClassList != null) {
			for (Class<?> clz : controllerClassList) {
				Class<?> clazz = null;
				try {
					clazz =Class.forName(clz.getName());
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				FileMeta fm = null;
				try {
					fm=  (FileMeta) clazz.newInstance();
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				fms.add(fm);
				System.out.println(clz.getName()+":"+fm.getFileName());
				
				//InputStream in = clz.getResourceAsStream(fm.getFileName());
				
			}
		}
		return fms;
	}
	public void start(){
		this.loadTableSettings();
		// 模版处理
		String tRoot = TEMPLATE_DISK+File.separatorChar+"CubeHandTemplates"+File.separatorChar;
		String OUTPUT_DIR = "G:/CubeHandOutput/"+_project.getNAME()+"/";
		
		FreeMarkerHelper fmh = new FreeMarkerHelper(tRoot);
		List<FileMeta> fms = this.getTemplates();
		for(FileMeta fm : fms){
			String outputPath = fm.getOutputPath();
			if(StrKit.isBlank(outputPath)){
				// == null的情况
				outputPath="";
				continue;
			}
			outputPath = outputPath.replaceAll("\\\\", "/");
			while(outputPath.indexOf("./")>-1){
				outputPath = outputPath.replaceAll("./", "/");
			}
			
			
			Class<?> clz = fm.getClass();
			
			if(fm.getGenType() == GenType.EACH){
				for(EntityVariable table:_tables){
					if(!table.getIS_PROCESS()){
						// 跳过不处理的表
						continue;
					}
					Map<String,Object> vars = new HashMap<String,Object>();
					vars.put("project", _projectJson);
					
					//vars.put("projectName", _project.getNAME());
					//vars.put("package", "com.mss.app");
					//vars.put("subpackage", table.getPREFIX().toLowerCase());
					
					GenerateVariable gv = new GenerateVariable();
					gv.setEntitys(_tables);
					gv.setPackageName("com.msteam.app");
					if(StrKit.isBlank(table.getPACKAGE_NAME())){
						gv.setSubPackageName(table.getPREFIX().toLowerCase());
					}else{
						gv.setSubPackageName(table.getPACKAGE_NAME());
					}
					vars.put("gen", gv);
					
					vars.put("entitys", _tables);
					vars.put("entity", table);
					
					//vars.put("modelName", table.getMODEL_NAME());
					//vars.put("subModelName", table.getSUB_MODEL_NAME());
					//vars.put("entity", entityMeta);
					//vars.put("modelName", entityMeta.modelName);
					//vars.put("tableName", this._mmbuilder.getTablePrefix()+entityMeta.name);
					fmh.clear();
					fmh.putAll(vars);
					
					
					String outputFileName = OUTPUT_DIR + outputPath;
					outputFileName = outputFileName.replaceAll("\\$\\{subpackage\\}", gv.getSubPackageName());
					outputFileName = outputFileName.replaceAll("\\$\\{packagePath\\}", (gv.getPackageName()).replaceAll("\\.", "/"));
					outputFileName = outputFileName.replaceAll("\\$\\{modelName\\}", table.getMODEL_NAME());
					outputFileName = outputFileName.replaceAll("\\$\\{submodelname\\}", table.getSUB_MODEL_NAME().toLowerCase());
					
					String fdir = outputFileName.substring(0, outputFileName.lastIndexOf("/"));
					File fd = new File(fdir);
					if(!fd.exists()){
						fd.mkdirs();
					}
					InputStream in = clz.getResourceAsStream(fm.getFileName());
					fmh.exec(in, outputFileName);
					
				}
			}else if(fm.getGenType() == GenType.ONCE){
				Map<String,Object> vars = new HashMap<String,Object>();
				vars.put("project", _projectJson);
				GenerateVariable gv = new GenerateVariable();
				gv.setEntitys(_tables);
				gv.setPackageName("com.msteam.app");
				gv.setSubPackageName("index");
				vars.put("gen", gv);
				//vars.put("package", "com.mss.app");
				//vars.put("subpackage", "index");
				vars.put("entitys", _tables);

				
				//vars.put("entity", entityMeta);
				//vars.put("modelName", entityMeta.modelName);
				//vars.put("tableName", this._mmbuilder.getTablePrefix()+entityMeta.name);
				fmh.clear();
				fmh.putAll(vars);
				
				
				String outputFileName = OUTPUT_DIR + outputPath;
				
				outputFileName = outputFileName.replaceAll("\\$\\{subpackage\\}", gv.getSubPackageName());
				outputFileName = outputFileName.replaceAll("\\$\\{packagePath\\}", (gv.getPackageName()).replaceAll("\\.", "/"));
				//outputFileName = outputFileName.replaceAll("\\$\\{modelName\\}", (String)vars.get("modelName"));
				
				String fdir = outputFileName.substring(0, outputFileName.lastIndexOf("/"));
				File fd = new File(fdir);
				if(!fd.exists()){
					fd.mkdirs();
				}
				InputStream in = clz.getResourceAsStream(fm.getFileName());
				fmh.exec(in, outputFileName);
			}else if(fm.getGenType() == GenType.STATIC){
				
			}else if(fm.getGenType() == GenType.UNZIP){
				
			}

			
		}
		
	}
	/**
	 * 开始生成
	 */
	public void start2(){
		this.loadTableSettings();
		CbhTemplate template = new CbhTemplate().findById(_project.getTemplateId());
		List<CbhTemplateFile> templateFiles = new CbhTemplateFile().find("select * from cbh_template_file where TEMPLATE_ID=?", template.getID());
		
		String tRoot = TEMPLATE_DISK+File.separatorChar+"CubeHandTemplates"+File.separatorChar+template.getCODE()+File.separatorChar;
		
		// 模版处理
		FreeMarkerHelper fmh = new FreeMarkerHelper(tRoot);

		
/*		String outputFile = _filenameTemplate.replace("${className}", name);
		
		String tablePrefix = PropKit.use("db.properties").get("db_tablePrefix");
		
		
		
		String dir = (this._outputDir+"/"+outputFile);
		dir = dir.substring(0, dir.lastIndexOf("/"));
		File f = new File(dir);
		if(!f.exists()){
			f.mkdirs();
		}
		fmh.exec(this._templateName, this._outputDir+"/"+outputFile);
		*/
		
		
		//String OUTPUT_DIR = PathKit.getWebRootPath() +"/WEB-INF/output/"+_project.getNAME()+"/";
		String OUTPUT_DIR = "G:/CubeHandOutput/"+_project.getNAME()+"/";
		
		
		for(CbhTemplateFile file: templateFiles){
			if(!"FILE".equalsIgnoreCase(file.getFileType())){
				continue;
			}
			String outputPath = file.getOutputPath();
			if(StrKit.isBlank(outputPath)){
				// == null的情况
				outputPath="";
			}
			outputPath = outputPath.replaceAll("\\\\", "/");
			while(outputPath.indexOf("./")>-1){
				outputPath = outputPath.replaceAll("./", "/");
			}
			
			if("static".equalsIgnoreCase(file.getProcessType())){
				Map<String,Object> vars = new HashMap<String,Object>();
				vars.put("project", _projectJson);
				vars.put("projectName", _project.getNAME());
				vars.put("package", "com.mss.app");
				vars.put("subpackage", "index");
				vars.put("entitys", _tables);

				
				//vars.put("entity", entityMeta);
				//vars.put("modelName", entityMeta.modelName);
				//vars.put("tableName", this._mmbuilder.getTablePrefix()+entityMeta.name);
				fmh.clear();
				fmh.putAll(vars);
				
				
				String outputFileName = OUTPUT_DIR + outputPath;
				outputFileName = outputFileName.replaceAll("\\$\\{subpackage\\}", (String)vars.get("subpackage"));
				outputFileName = outputFileName.replaceAll("\\$\\{packagePath\\}", ((String)vars.get("package")).replaceAll("\\.", "/"));
				//outputFileName = outputFileName.replaceAll("\\$\\{modelName\\}", (String)vars.get("modelName"));
				
				String fdir = outputFileName.substring(0, outputFileName.lastIndexOf("/"));
				File fd = new File(fdir);
				if(!fd.exists()){
					fd.mkdirs();
				}
				try {
					FileUtils.copyFile(new File(tRoot+file.getPATH()), new File(outputFileName));
				} catch (IOException e) {
					e.printStackTrace();
				}

			}else if("unzip".equalsIgnoreCase(file.getProcessType())){
				try {
					com.msteam.kernel.util.FileUtils.unzip(tRoot+file.getPATH(), OUTPUT_DIR+file.getOutputPath());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}else if("once".equalsIgnoreCase(file.getProcessType())){
				Map<String,Object> vars = new HashMap<String,Object>();
				vars.put("project", _projectJson);
				vars.put("projectName", _project.getNAME());
				vars.put("package", "com.mss.app");
				vars.put("subpackage", "index");
				vars.put("entitys", _tables);

				
				//vars.put("entity", entityMeta);
				//vars.put("modelName", entityMeta.modelName);
				//vars.put("tableName", this._mmbuilder.getTablePrefix()+entityMeta.name);
				fmh.clear();
				fmh.putAll(vars);
				
				
				String outputFileName = OUTPUT_DIR + outputPath;
				
				outputFileName = outputFileName.replaceAll("\\$\\{subpackage\\}", (String)vars.get("subpackage"));
				outputFileName = outputFileName.replaceAll("\\$\\{packagePath\\}", ((String)vars.get("package")).replaceAll("\\.", "/"));
				//outputFileName = outputFileName.replaceAll("\\$\\{modelName\\}", (String)vars.get("modelName"));
				
				String fdir = outputFileName.substring(0, outputFileName.lastIndexOf("/"));
				File fd = new File(fdir);
				if(!fd.exists()){
					fd.mkdirs();
				}
				
				fmh.exec(file.getPATH(), outputFileName);
			}else if("each".equalsIgnoreCase(file.getProcessType())){
				for(CbhTableJson table:_tables){
					if(!table.getIS_PROCESS()){
						// 跳过不处理的表
						continue;
					}
					Map<String,Object> vars = new HashMap<String,Object>();
					vars.put("project", _projectJson);
					vars.put("projectName", _project.getNAME());
					vars.put("package", "com.mss.app");
					vars.put("subpackage", table.getPREFIX().toLowerCase());
					vars.put("entitys", _tables);
					vars.put("entity", table);
					vars.put("modelName", table.getMODEL_NAME());
					vars.put("subModelName", table.getSUB_MODEL_NAME());
					//vars.put("entity", entityMeta);
					//vars.put("modelName", entityMeta.modelName);
					//vars.put("tableName", this._mmbuilder.getTablePrefix()+entityMeta.name);
					fmh.clear();
					fmh.putAll(vars);
					
					
					String outputFileName = OUTPUT_DIR + outputPath;
					outputFileName = outputFileName.replaceAll("\\$\\{subpackage\\}", (String)vars.get("subpackage"));
					outputFileName = outputFileName.replaceAll("\\$\\{packagePath\\}", ((String)vars.get("package")).replaceAll("\\.", "/"));
					outputFileName = outputFileName.replaceAll("\\$\\{modelName\\}", (String)vars.get("modelName"));
					outputFileName = outputFileName.replaceAll("\\$\\{submodelname\\}", table.getSUB_MODEL_NAME().toLowerCase());
					
					String fdir = outputFileName.substring(0, outputFileName.lastIndexOf("/"));
					File fd = new File(fdir);
					if(!fd.exists()){
						fd.mkdirs();
					}
					
					fmh.exec(file.getPATH(), outputFileName);
					
				}
			}
			
		}
	}

	
	/**
	 * 生成
	 * @param tableMetas
	 */
/*	public void generate(List<TableMeta> tableMetas) {
		System.out.println("Generate ...");
		for (TableMeta tableMeta : tableMetas){
			gen(tableMeta);
		}
	}
	private EntityMetadata wrapperEntityMeta(TableMeta tm){
		EntityMetadata em = new EntityMetadata();
		em.setBaseModelContent(tm.baseModelContent);
		em.setBaseModelName(tm.baseModelName);
		em.setColDefaultValueMaxLen(tm.colDefaultValueMaxLen);
		em.setColNameMaxLen(tm.colNameMaxLen);
		em.setColTypeMaxLen(tm.colTypeMaxLen);
		em.setModelContent(tm.modelContent);
		em.setModelName(tm.modelName);
		em.setName(tm.name);
		em.setPrimaryKey(tm.primaryKey);
		em.setRemarks(tm.remarks);
		List<FieldMetadata> fields = new ArrayList<FieldMetadata>();
		for(ColumnMeta cm : tm.columnMetas){
			FieldMetadata fm = new FieldMetadata();
			fm.setAttrName(cm.attrName);
			fm.setDefaultValue(cm.defaultValue);
			fm.setIsNullable(cm.isNullable);
			if(cm.name.equalsIgnoreCase(tm.primaryKey)){
				fm.setIsPrimaryKey(true);
			}else{
				fm.setIsPrimaryKey(false);
			}
			fm.setJavaType(cm.javaType);
			fm.setName(cm.name);
			fm.setRemarks(cm.remarks);
			fm.setType(cm.type);
			fields.add(fm);
		}
		
		em.setFields(fields);
		return em;
	}
	protected void gen(TableMeta tm){
		
		EntityMetadata entityMeta = wrapperEntityMeta(tm);
		// 模版处理
		FreeMarkerHelper fmh = new FreeMarkerHelper(PathKit.getWebRootPath() +"/WEB-INF/templates/");
		String name = "";
		if(this._namingMode == NamingMode.CAMEL_CASE){
			name = StrKit.firstCharToLowerCase(StrKit.toCamelCase(entityMeta.name));
		}else if(this._namingMode == NamingMode.PASCAL_CASE){
			name = StrKit.firstCharToUpperCase(StrKit.toCamelCase(entityMeta.name));
		}else if(this._namingMode == NamingMode.LOWER_CONNECT_CASE){
			name = entityMeta.name.toLowerCase().replaceAll("_", "");
		}else if(this._namingMode == NamingMode.LOWER_SPLIT_CASE){
			name = entityMeta.name.toLowerCase();
		}else if(this._namingMode == NamingMode.UPPER_CONNECT_CASE){
			name = entityMeta.name.toUpperCase().replaceAll("_", "");
		}else if(this._namingMode == NamingMode.UPPER_SPLIT_CASE){
			name = entityMeta.name.toUpperCase();
		}
		
		String outputFile = _filenameTemplate.replace("${className}", name);
		
		String tablePrefix = PropKit.use("db.properties").get("db_tablePrefix");
		
		Map<String,Object> vars = new HashMap<String,Object>();
		vars.put("projectName", "项目名称");
		vars.put("packageName", this._packageName);
		vars.put("entity", entityMeta);
		vars.put("modelName", entityMeta.modelName);
		vars.put("tableName", this._mmbuilder.getTablePrefix()+entityMeta.name);
		fmh.putAll(vars);
		
		String dir = (this._outputDir+"/"+outputFile);
		dir = dir.substring(0, dir.lastIndexOf("/"));
		File f = new File(dir);
		if(!f.exists()){
			f.mkdirs();
		}
		fmh.exec(this._templateName, this._outputDir+"/"+outputFile);
	}*/
	
	private CbhProjectJson _wrapCbhProjectJsonItem(CbhProject objItem){
		List<CbhProjectJson> jsonItems = new ArrayList<CbhProjectJson>();
		
			CbhProjectJson jsonItem = new CbhProjectJson();
			jsonItem.setID(objItem.getID());
			jsonItem.setNAME(objItem.getNAME());
			jsonItem.setTEMPLATE_ID(objItem.getTemplateId());
			jsonItem.setVERSION(objItem.getVERSION());
			jsonItem.setDESCRIPTION(objItem.getDESCRIPTION());
			jsonItem.setAUTHOR(objItem.getAUTHOR());
			jsonItem.setCREATE_DATE(objItem.getCreateDate());
			jsonItem.setVERSION_DATE(objItem.getVersionDate());
			jsonItem.setTABLE_PREFIX(objItem.getTablePrefix());
			jsonItem.setDB_HOST(objItem.getDbHost());
			jsonItem.setDB_NAME(objItem.getDbName());
			jsonItem.setDB_USER(objItem.getDbUser());
			jsonItem.setDB_PASSWORD(objItem.getDbPassword());
		
		return jsonItem;
	}
}
